/************************************************************************
 * The code is owned by mainframer.cn and Shang Tao
 * Without aproval of mainframer.cn and Shang Tao, remove the copyright
 * infomation is regarded invassion of proprietary copyright
 ***********************************************************************/
package com.mr.qa.action;

import java.util.Date;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionMessage;
import org.apache.struts.action.ActionMessages;
import org.apache.struts.upload.FormFile;
import org.hibernate.Transaction;

import com.mr.qa.UserSession;
import com.mr.qa.UserSessionUtil;
import com.mr.qa.bo.Answer;
import com.mr.qa.bo.Question;
import com.mr.qa.bo.User;
import com.mr.qa.dao.impl.AnswerDAO;
import com.mr.qa.dao.impl.QuestionDAO;
import com.mr.qa.dao.impl.UserDAO;
import com.mr.qa.dao.impl.UserScoreHistoryConstants;
import com.mr.qa.exception.QaException;
import com.mr.qa.form.AnswerForm;
import com.mr.qa.util.HibernateSessionFactory;

public class AnswerAction extends BaseAction {

    private static final Log log = LogFactory.getLog(AnswerAction.class);

    //private static final int ANSWERS_SIZE_PER_VIEW_QUESTION_PAGE = GlobalConfigs.NUMBER_ANSWER_FOR_VIEW_QUESTION;

    public ActionForward doAction(ActionMapping mapping, ActionForm form,
			HttpServletRequest request, HttpServletResponse response) throws QaException
    {
        ActionForward af = null;
        UserSession us = UserSessionUtil.getUserSession(request);
        String action = this.getAction(request);
        ActionMessages errors = new ActionMessages();
        ActionMessages messages = new ActionMessages();
        AnswerForm answerForm = (AnswerForm)form;
        String idStr = answerForm.getId();
        Integer answerId = null;
        if(idStr != null && idStr.length() > 0)
        {
            try
            {
                answerId = new Integer(idStr);
            }
            catch(Exception e){}
        }
        int page = answerForm.getPage();
        if(page == 0)page = 1;
        int pageSize = answerForm.getPageSize();
        if(pageSize == 0)
        {
                pageSize = 15;
        }
        request.setAttribute("pageSize",""+pageSize);
        if("add".equals(action))
        {
            if(us == null)
            {
                //2008.03.09
                //entering a confirmation page to add answer directly or login
                /*
                errors.add("relogin", new ActionMessage("login.required"));
                action = "login";
                */
                String originalUrl = request.getRequestURI()+"?action=add&content="
                +answerForm.getContent()+"&anonymous="
                +answerForm.getAnonymous()+"&questionId="
                +answerForm.getQuestionId()+"&reference="+answerForm.getReference();
                request.setAttribute(this.ORIGINAL_URL_NAME,originalUrl);
                action = "addanswerconfirmforanonymoususer";
            }
            else if(!us.isActive()){
            	errors.add("addquestion-limit", new ActionMessage("user.inactive", ""));
            	String path = mapping.findForward(action).getPath();
                path = path.replace("!?",answerForm.getQuestionId());
                af = new ActionForward(path+"&gotoLastPage=true");
                af.setRedirect(true);
            }
            else
            {
                add(answerForm,us.getUserId(),request.getRemoteAddr());
                String path = mapping.findForward(action).getPath();
                path = path.replace("!?",answerForm.getQuestionId());
                af = new ActionForward(path+"&gotoLastPage=true");
                af.setRedirect(true);
            }
        }/*
        else if("anonymouslyadd".equals(action))
        {
            String vc = answerForm.getVc();
            if(vc == null)vc = "";
            String vcinSession = UserSessionUtil.getVerificationCodes(request);
            if(vc.length() == 0)
            {
                errors.add("vc", new ActionMessage("verificationcode.required"));
                request.setAttribute(this.ORIGINAL_URL_NAME,
                request.getParameter(this.ORIGINAL_URL_NAME));
                action = "addanswerconfirmforanonymoususer";
            }
            else if(!vc.equals(vcinSession))
            {
                errors.add("vc", new ActionMessage("verificationcode.error"));
                request.setAttribute(this.ORIGINAL_URL_NAME,
                request.getParameter(this.ORIGINAL_URL_NAME));
                action = "addanswerconfirmforanonymoususer";
            }
            else
            {
                anonymouslyAdd(answerForm,request.getRemoteAddr());
                String path = mapping.findForward(action).getPath();
                path = path.replace("!?",answerForm.getQuestionId());
                af = new ActionForward(path+"&gotoLastPage=true");
                af.setRedirect(true);
            }
        }*/
        else if("predelete".equals(action))
        {
            if(answerId == null)
            {
                errors.add("duplicatedelete", new ActionMessage("answer.delete.noanswer"));
                af = mapping.findForward("error");
            }
            else
            {
                Answer answer = this.view(answerId);
                if(answer == null)
                {
                    errors.add("duplicatedelete", new ActionMessage("answer.delete.noanswer"));
                    af = mapping.findForward("error");
                }
                else
                {
                    request.setAttribute("answer",answer);
                }
            }
        }
        else if("idelete".equals(action))
        {
            delete(answerId,us.getUserId(),us.getType(),
            us.getIsSuper(),us.getPermissions(),errors);
            messages.add("deletesuccess", new ActionMessage("answer.delete.success"));
        }
        else if("delete".equals(action))
        {
            String vc = answerForm.getVc();
            if(vc == null)vc = "";
            String vcinSession = UserSessionUtil.getVerificationCodes(request);
            if(vc.length() == 0)
            {
                errors.add("vc", new ActionMessage("verificationcode.required"));
                String path = mapping.findForward("deletefailure").getPath();
                path = path.replace("!?",""+answerId);
                af = new ActionForward(path);
                af.setRedirect(true);
            }
            else if(!vc.equals(vcinSession))
            {
                errors.add("vc", new ActionMessage("verificationcode.error"));
                String path = mapping.findForward("deletefailure").getPath();
                path = path.replace("!?",""+answerId);
                af = new ActionForward(path);
                af.setRedirect(true);
            }
            else
            {
                if(us == null)
                {
                    errors.add("relogin", new ActionMessage("login.required"));
                    action = "relogin";
                }
                else
                {
                    Integer questionId = delete(answerId,us.getUserId(),us.getType()
                        ,us.getIsSuper(),us.getPermissions(),errors);
                    log.info("questionId:"+questionId+" after delete answer:"+answerId);
                    //add a error page, if questionId == null, forward to error page
                    if(questionId != null)
                    {
                        String path = mapping.findForward(action).getPath();
                        path = path.replace("!?",""+questionId);
                        af = new ActionForward(path);
                        af.setRedirect(true);
                        messages.add("deletesuccess", new ActionMessage("answer.delete.success"));
                    }
                    else
                    {
                        af = mapping.findForward("error");
                    }
                }
            }
        }/*
        else if("hide".equals(action))
        {
            update(answerId, true);
        }*/
        else if("premodify".equals(action))
        {
            request.setAttribute("answero",view(answerId));
        }
        else if("modify".equals(action))
        {
            Integer questionId = modify(answerForm,us.getUserId());
            String path = mapping.findForward(action).getPath();
            path = path.replace("!?",""+questionId);
            path = path+"&page="+page+"&pageSize="+pageSize;
            af = new ActionForward(path);
            af.setRedirect(true);
        }/*
        else if("close".equals(action))
        {
            update(answerId, false);
        }*/
        if(af == null)
            return mapping.findForward(action);
        if(errors.size() > 0 || messages.size() > 0)
        {
            if(!af.getRedirect())
            {
                saveErrors(request, errors);
                saveMessages(request, messages);
            }
            else
            {
                saveErrors(request.getSession(), errors);
                saveMessages(request.getSession(), messages);
            }
        }
        return af;
    }
	
	public Answer view(Integer id) throws QaException
        {
	    Transaction tx = null;
            try
            {
                tx = HibernateSessionFactory.getSession().beginTransaction();
		AnswerDAO answerDAO = new AnswerDAO();
		Answer answer = answerDAO.findById(id);
                tx.commit();
		return answer;
            }
	    catch(Exception e)
	    {
	        if(tx != null)tx.rollback();
	        throw new QaException(e);
	    }
	    finally
	    {
	        HibernateSessionFactory.closeSession();  
	    }
            
	}
	
        
	private void add(AnswerForm answerForm,Integer userId,String userIp) throws QaException
        {
            Transaction tx = null;
            try
            {
                AnswerDAO answerDAO = new AnswerDAO();
                UserDAO userDAO = new UserDAO();
                QuestionDAO questionDAO = new QuestionDAO();
                tx = HibernateSessionFactory.getSession().beginTransaction();
                User user = null;
                user = userDAO.findById(userId);
                String questionId = answerForm.getQuestionId();
                if(questionId == null || questionId.length() == 0)
                {
                    throw new QaException("Question id is required");
                }
                Integer intQuestionId = new Integer(questionId);
                Question question = questionDAO.findById(intQuestionId);
                String content = answerForm.getContent();
                String reference = answerForm.getReference();
                Answer answer = new Answer();
                answer.setContent(content);
                answer.setReference(reference);
                Date date = new Date();
                answer.setPostDate(date);
                question.setChangeDate(date);
                //question.setPostDate(date);
                answer.setMrIaskUser(user);
                answer.setMrIaskQuestion(question);
                String state = answerForm.getState();
                if(state == null)state = "0";
                if(state.length() == 0)state = "0";
                answer.setState(state);
                answer.setPollCount(0);
                /*
                FormFile file = answerForm.getFile();
                String fName = "";
                if(file != null)fName = file.getFileName();
                if(fName.length() > 0)
                {
                    answer.setFileName(fName);
                }*/
                String catType = question.getMrIaskCategory().getOnlyForAdmin(); 
                if("T".equals(catType))
                {
                    answer.setState("1");//answer in a topic defaultly set as poll item
                }
                //2009.1.20 //userIp
                answer.setAnonymousUser(userIp); //add 2009.8.29
                if(answerForm.getAnonymous()) {
                    //answer.setAnonymousUser(userIp); //remove 2009.8.29
                    answer.setIsAnonymous(true);
                }
                answerDAO.save(answer);
                questionDAO.update(question);
                //answering anonymously does nnot score 2009.1.30 23:57
                boolean addScore = true;
                if(answerForm.getAnonymous())
                    addScore = false;
                else if("I".equals(catType)) {
                    addScore = false;
                }
                if(addScore)
                answerDAO.addScoreHistory(user,answer.getId(),"", 
                UserScoreHistoryConstants.USER_SCORE_HISTORY_ADD_ANSWER,"add answer");
                tx.commit();
            } 
            catch(Exception re)
            {
                if(tx != null)tx.rollback();
                throw new QaException(re);
            }
            finally
            {
                HibernateSessionFactory.closeSession();
            }
	}
    /*
     * @ Depredicated
     */
    private void anonymouslyAdd(AnswerForm answerForm,String userInfo) throws QaException
    {
        Transaction tx = null;
        try
        {
            AnswerDAO answerDAO = new AnswerDAO();
            QuestionDAO questionDAO = new QuestionDAO();
            tx = HibernateSessionFactory.getSession().beginTransaction();
            String questionId = answerForm.getQuestionId();
            if(questionId == null || questionId.length() == 0)
            {
                throw new QaException("Question id is required");
            }
            Question question = questionDAO.findById(new Integer(questionId));
            String content = answerForm.getContent();
            String reference = answerForm.getReference();
            Answer answer = new Answer();
            answer.setContent(content);
            answer.setReference(reference);
            Date date = new Date();
            answer.setPostDate(date);
            answer.setAnonymousUser(userInfo);
            question.setChangeDate(date);
            //question.setPostDate(date);
            answer.setMrIaskQuestion(question);
            String state = answerForm.getState();
            if(state == null)state = "0";
            if(state.length() == 0)state = "0";
            answer.setState(state);
            answer.setPollCount(0);
            FormFile file = answerForm.getFile();
            String fName = "";
            if(file != null)fName = file.getFileName();
            if(fName.length() > 0)
            {
                answer.setFileName(fName);
            }
            if("T".equals(question.getMrIaskCategory().getOnlyForAdmin()))
            {
                answer.setState("1");//answer in a topic defaultly set as poll item
            }
            answerDAO.save(answer);
            questionDAO.update(question);
            tx.commit();
        } 
        catch(Exception re)
        {
            if(tx != null)tx.rollback();
            throw new QaException(re);
        }
        finally
        {
            HibernateSessionFactory.closeSession();
        }
    }


    /**
     * return the id of the question of the answer
     * @param answerForm
     * @param userId
     * @return
     * @throws QaException
     */
    private Integer modify(AnswerForm answerForm,Integer userId) throws QaException
    {
        Transaction tx = null;
        Integer questionId;
        try
        {
            AnswerDAO answerDAO = new AnswerDAO();
            tx = HibernateSessionFactory.getSession().beginTransaction();
            Answer answer = answerDAO.findById(new Integer(answerForm.getId()));
            questionId = answer.getMrIaskQuestion().getId();
            String content = answerForm.getContent();
            String reference = answerForm.getReference();
            answer.setContent(content);
            answer.setReference(reference);
            Date date = new Date();
            //answer.setPostDate(date);
            //answer.setIsAnonymous(false);
            FormFile file = answerForm.getFile();
            String fName = "";
            if(file != null)fName = file.getFileName();
            if(fName.length() > 0)
            {
                answer.setFileName(fName);
            }
            Question question = answer.getMrIaskQuestion();
            //question.setPostDate(date);
            question.setChangeDate(date);
            new QuestionDAO().update(question);
            answerDAO.update(answer);
            tx.commit();
        } 
        catch(Exception re)
        {
            if(tx != null)tx.rollback();
            throw new QaException(re);
        }
        finally
        {
            HibernateSessionFactory.closeSession();
        }
        return questionId;
    }
	
	public Integer delete(Integer answerId,Integer userId,String userType,boolean isSuperUser,String userPermissions,ActionMessages errors) throws QaException
        {
            Transaction tx = null;
            Integer questionId = null;
            try 
            {
                AnswerDAO answerDAO = new AnswerDAO();                
                tx = HibernateSessionFactory.getSession().beginTransaction();
                Answer answer = answerDAO.findById(answerId);
                questionId = answer.getMrIaskQuestion().getId();
                //log.info("found question:"+questionId+" of answer"+answerId);
                String categoryId = answer.getMrIaskQuestion().getMrIaskCategory().getId()+"";
                Integer answerUserId = (answer.getMrIaskUser() == null)?null:(answer.getMrIaskUser().getId());
                boolean userHasRight = false;
                if("1".equals(userType))
                {
                    userHasRight = true;
                }
                else
                {
                    if(userId.equals(answerUserId))
                    {
                        userHasRight = true;
                    }
                    else
                    {
                        if(isSuperUser)
                        {
                            if(userPermissions != null && userPermissions.trim().length() > 0)
                            {
                                if(userPermissions.indexOf(categoryId+",") >= 0)
                                    userHasRight = true;
                            }
                        }
                    }
                }
                log.info("user:"+userId+" has right to delete answer:"+answerId+" ?"+userHasRight);
                //here
                if(!userHasRight)
                {
                    errors.add("noright", new ActionMessage("user.noright"));
                }
                else
                {
                    answerDAO.delete(answer);
                    //if("1".equals(userType))
                    if(answer.getMrIaskUser() != null)
                    {
                        if(userId.equals(answer.getMrIaskUser().getId()))
                        {
                            answerDAO.addScoreHistory(answer.getMrIaskUser(),
                            answer.getId(),"",
                            UserScoreHistoryConstants.USER_SCORE_HISTORY_DELETE_ANSWER_BY_SELF
                            ,"delete answer by self");
                        }
                        else
                        {
                            answerDAO.addScoreHistory(answer.getMrIaskUser(),
                            answer.getId(),"",UserScoreHistoryConstants.
                            USER_SCORE_HISTORY_DELETE_ANSWER_BY_ADMIN,"delete answer by admin id:"+userId);
                        }
                    }
                    tx.commit();
                }
                /*
                try
                {
                    File file = new File(path);
                    if(file.exists()){
		                file.delete();
                    }
                }
                catch(Exception e)
                {
                    log.error(e);
                }*/
            }
            catch(NullPointerException npe)
            {
                errors.add("duplicatedelete", new ActionMessage("answer.delete.noanswer"));
                log.info("When user:"+userId+" deletes answer:"+answerId+", NullPointerException:"+npe);
                if (tx != null)tx.rollback();
            }
	    catch(Exception re)
	    {
	        errors.add("deletefailure", new ActionMessage("answer.delete.failure"));
	        log.info("When user:"+userId+" deletes answer:"+answerId+", exception:"+re);
	        if (tx != null)tx.rollback();
	        throw new QaException(re);
	    }
            finally
            {
                HibernateSessionFactory.closeSession();                
            }
            return questionId;
	}
}
